package com.yyfax.pay.depository.service;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import com.yyfax.commons.lang.DateUtil;
import com.yyfax.framework.common.Log;
import com.yyfax.pay.common.enums.FuiouBusiTypeEnum;
import com.yyfax.pay.common.enums.FuiouDepositStateEnum;
import com.yyfax.pay.common.exception.PayExceptionCode;
import com.yyfax.pay.common.util.FuiouIdUtils;
import com.yyfax.pay.depository.dao.FuiouUnfrozenDao;
import com.yyfax.pay.depository.domain.FuiouUnfrozen;
import com.yyfax.pay.depository.service.inner.FuiouDepositCommonService;
import com.yyfax.pay.service.depository.UnfrozenService;
import com.yyfax.pay.third.facade.fuioudeposit.FuiouDepositService;
import com.yyfax.pay.third.facade.fuioudeposit.FuiouDepositTradeService;
import com.yyfax.pay.third.facade.fuioudeposit.FuiouSignService;
import com.yyfax.pay.third.service.PayInfoConstantService;
import com.yyfax.pay.vo.depository.TradeRsp;
import com.yyfax.pay.vo.depository.UnfrozenReq;

/**
 * 解冻服务实现
 * 
 * @author heizq
 * @date 2017-09-02 10:09:11
 * @since v1.0.0
 */
@Service
public class UnfrozenServiceImpl implements UnfrozenService {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    private FuiouIdUtils fuiouIdUtils;

    @Resource
    private FuiouUnfrozenDao fuiouUnfrozenDao;

    @Resource
    private PayInfoConstantService payInfoConstantService;

    @Resource
    private FuiouSignService fuiouSignService;

    @Resource
    private FuiouDepositService fuiouDepositService;

    @Resource
    private FuiouDepositCommonService fuiouDepositCommonService;

    @Resource
    private FuiouDepositTradeService fuiouDepositTradeService;

    @Override
    public TradeRsp unfrozen(UnfrozenReq req, String merchantCode) {
        // 1.保存订单
        FuiouUnfrozen domain = buildDomain(req, merchantCode);

        TradeRsp tradeRsp = checkOrder(domain);
        if (tradeRsp != null) {
            return tradeRsp;
        }

        // 2.修改订单状态处理中
        int updateResult =
                fuiouUnfrozenDao.updateStateById(FuiouDepositStateEnum.DEALING.getValue(), FuiouDepositStateEnum.INI.getValue(), domain.getBusiId(), DateUtil.getCurrentDateTime());
        if (updateResult <= 0) {
            return new TradeRsp(PayExceptionCode.PROCESSING.getCode(), PayExceptionCode.PROCESSING.getDesc(), domain.getBusiId());
        }

        // 3. 发请求
        TradeRsp result = fuiouDepositTradeService.unfrozen(domain);

        // 4. 根据响应更新订单状态
        updateOrderState(result, domain);
        return result;
    }

    /**
     * 封装数据实体
     * 
     * @author heizq
     * @date 2017-09-02 10:46:03
     * @since v1.0.0
     * @param req
     * @param merchantCode
     * @return
     */
    private FuiouUnfrozen buildDomain(UnfrozenReq req, String merchantCode) {
        String op = "UnfrozenServiceImpl.buildDomain";

        FuiouUnfrozen domain = new FuiouUnfrozen();
        domain.setBusiId(fuiouIdUtils.generateBusiId(FuiouBusiTypeEnum.UNFROZEN, merchantCode));
        domain.setOrderId(req.getOrderId());
        domain.setMerchantCode(merchantCode);
        domain.setOrderTime(DateUtil.datetime2Str(req.getOrderTime()));
        domain.setState(FuiouDepositStateEnum.INI.getValue());
        domain.setAccountNo(req.getAccountNo());
        domain.setAmount(req.getAmount());
        domain.setTerminal(req.getTerminal());
        domain.setRemark(req.getRemark());
        String currentDate = DateUtil.getCurrentDateTime();
        domain.setCreateTime(currentDate);
        domain.setUpdateTime(currentDate);

        try {
            fuiouUnfrozenDao.insert(domain);
        } catch (DuplicateKeyException e) {
            logger.info(Log.op(op).msg("【富友存管-解冻】订单已存在！").kv("orderId", domain.getOrderId()).kv("merchantCode", merchantCode).toString());
            domain = fuiouUnfrozenDao.selectByOrderIdMerchantCode(req.getOrderId(), merchantCode);
            if (domain == null) {
                logger.error(Log.op(op).msg("保存订单信息主键冲突,查询订单的不存在").kv("merchantCode", merchantCode).kv("orderId", req.getOrderId()).toString());
                throw PayExceptionCode.ORDER_NOT_FOUND.exp();
            }
        }

        return domain;
    }

    /**
     * 解析响应结果
     * 
     * @author heizq
     * @date 2017-09-04 11:38:48
     * @since v1.0.0
     * @param rsp
     * @param merchantCode 商户号
     * @param busiId 业务主键
     */
    private void updateOrderState(TradeRsp rsp, FuiouUnfrozen domain) {
        final String op = "FrozenServiceImpl.dealRsp";

        // 超时或待确认
        if (PayExceptionCode.WARN_REQ_TIME_OUT.isCode(rsp.getCode()) || PayExceptionCode.TO_CONFIRM.isCode(rsp.getCode())) {
            logger.info(Log.op(op).msg("【富友存管-解冻】请求超时，插入主动查询").kv("busiId", domain.getBusiId()).toString());
            fuiouDepositCommonService.saveQueryTask(domain.getMerchantCode(), domain.getBusiId(), FuiouBusiTypeEnum.TRADE_QUERY);
            fuiouUnfrozenDao.updateCodeAndMsgByBusiId(domain.getBusiId(), DateUtil.getCurrentDateTime(), rsp.getCode(), rsp.getDisplay());
            return;
        }

        // 成功更新状态成功，其他都是失败
        if (PayExceptionCode.SUCCESS.isCode(rsp.getCode())) {
            fuiouUnfrozenDao.updateStateAndRspById(FuiouDepositStateEnum.SUCCESS.getValue(), FuiouDepositStateEnum.DEALING.getValue(), domain.getBusiId(),
                    DateUtil.getCurrentDateTime(), rsp.getCode(), rsp.getDisplay());
            logger.info(Log.op(op).msg("【富友存管-解冻】成功").kv("busiId", domain.getBusiId()).toString());
        } else {
            logger.warn(Log.op(op).msg("【富友存管-解冻】失败").kv("busiId", domain.getBusiId()).toString());
            fuiouUnfrozenDao.updateStateAndRspById(FuiouDepositStateEnum.FAIL.getValue(), FuiouDepositStateEnum.DEALING.getValue(), domain.getBusiId(),
                    DateUtil.getCurrentDateTime(), rsp.getCode(), rsp.getDisplay());
        }
    }

    /**
     * 订单状态检查
     * 
     * @author heizq
     * @date 2017-09-21 09:09:51
     * @since v1.0.0
     * @param domain
     * @return
     */
    private TradeRsp checkOrder(FuiouUnfrozen domain) {
        // 处理中的直接返回
        if (FuiouDepositStateEnum.DEALING.getValue().equals(domain.getState())) {
            return new TradeRsp(PayExceptionCode.PROCESSING.getCode(), PayExceptionCode.PROCESSING.getDesc(), domain.getBusiId());
        }

        if (FuiouDepositStateEnum.SUCCESS.getValue().equals(domain.getState())) {
            return new TradeRsp(PayExceptionCode.SUCCESS.getCode(), PayExceptionCode.SUCCESS.getDesc(), domain.getBusiId());
        }

        if (FuiouDepositStateEnum.FAIL.getValue().equals(domain.getState())) {
            return new TradeRsp(domain.getRespCode(), domain.getRespMsg(), domain.getBusiId());
        }
        return null;
    }
}
